import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
import type { Key } from 'ant-design-vue/es/vc-tree/interface';

import type { ExtractPropTypes, PropType } from 'vue';

import type { PermModeEnum } from '@vben/access';
import type { Fn, Recordable } from '@vben/types';

import type { ContextMenuItem } from '#/components/context-menu';

import { buildProps } from '#/utils/props';

export enum ToolbarEnum {
  SELECT_ALL,
  UN_SELECT_ALL,
  EXPAND_ALL,
  UN_EXPAND_ALL,
  CHECK_STRICTLY,
  CHECK_UN_STRICTLY,
}

export const treeEmits = [
  'update:expandedKeys',
  'update:selectedKeys',
  'update:value',
  'change',
  'check',
  'update:searchValue',
];

export interface TreeState {
  expandedKeys: Key[];
  selectedKeys: Key[];
  // 当设置checkable和checkStrictly，它是一个有checked和halfChecked属性的对象，并且父子节点的选中与否不再关联
  checkedKeys: CheckKeys;
  // checkable 状态下节点选择完全受控（父子节点选中状态不再关联）
  checkStrictly: boolean;
}

export interface FieldNames {
  children?: string;
  title?: string;
  key?: string;
}

export type CheckStrictlyKeys = {
  checked: Key[];
  halfChecked: Key[];
};

export type CheckKeys = CheckStrictlyKeys | Key[];

export const treeProps = buildProps({
  value: {
    type: [Object, Array] as PropType<CheckKeys | Key[]>,
  },

  renderIcon: {
    type: Function as PropType<(params: Recordable) => string>,
  },

  helpMessage: {
    type: [String, Array] as PropType<string | string[]>,
    default: '',
  },

  title: {
    type: String,
    default: '',
  },
  toolbar: {
    type: Boolean,
    default: true,
  },
  search: {
    type: Boolean,
    default: true,
  },
  searchValue: {
    type: String,
    default: '',
  },
  checkStrictly: {
    type: Boolean,
    default: false,
  },
  clickRowToExpand: {
    type: Boolean,
    default: false,
  },
  checkable: {
    type: Boolean,
    default: false,
  },
  defaultExpandLevel: {
    type: [String, Number] as PropType<number | string>,
    default: '',
  },
  defaultExpandAll: {
    type: Boolean,
    default: false,
  },
  // 工具栏是否显示 层级关联
  toolbarStrictly: {
    type: Boolean,
    default: true,
  },
  fieldNames: {
    type: Object as PropType<FieldNames>,
  },

  treeData: {
    type: Array as PropType<TreeDataItem[]>,
  },

  actionList: {
    type: Array as PropType<TreeActionItem[]>,
    default: () => [],
  },

  expandedKeys: {
    type: Array as PropType<Key[]>,
    default: () => [],
  },

  selectedKeys: {
    type: Array as PropType<Key[]>,
    default: () => [],
  },

  checkedKeys: {
    type: [Array, Object] as PropType<CheckKeys>,
    default: () => [],
  },

  beforeRightClick: {
    type: Function as PropType<
      (...arg: any) => ContextMenuItem[] | ContextMenuOptions
    >,
    default: undefined,
  },

  rightMenuList: {
    type: Array as PropType<ContextMenuItem[]>,
  },
  // 自定义数据过滤判断方法(注: 不是整个过滤方法，而是内置过滤的判断方法，用于增强原本仅能通过title进行过滤的方式)
  filterFn: {
    type: Function as PropType<
      (searchValue: any, node: TreeItem, fieldNames: FieldNames) => boolean
    >,
    default: undefined,
  },
  // 高亮搜索值，仅高亮具体匹配值（通过title）值为true时使用默认色值，值为#xxx时使用此值替代且高亮开启
  highlight: {
    type: [Boolean, String] as PropType<boolean | string>,
    default: false,
  },
  // 搜索完成时自动展开结果
  expandOnSearch: {
    type: Boolean,
    default: false,
  },
  // 搜索完成自动选中所有结果,当且仅当 checkable===true 时生效
  checkOnSearch: {
    type: Boolean,
    default: false,
  },
  // 搜索完成自动select所有结果
  selectedOnSearch: {
    type: Boolean,
    default: false,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  treeWrapperClassName: {
    type: String,
    default: '',
  },
});

export type TreeProps = ExtractPropTypes<typeof treeProps>;

export interface ContextMenuOptions {
  icon?: string;
  styles?: any;
  items?: ContextMenuItem[];
}

export interface TreeItem extends TreeDataItem {
  icon?: any;
}

export interface TreeActionItem {
  render: (record: Recordable) => any;
  show?: ((record: Recordable) => boolean) | boolean;
  auth?: string | string[];
  authMode?: PermModeEnum;
}

export interface InsertNodeParams {
  parentKey: null | string;
  node: TreeDataItem;
  list?: TreeDataItem[];
  push?: 'push' | 'unshift';
}

export interface TreeActionType {
  checkAll: (checkAll: boolean) => void;
  expandAll: (expandAll: boolean) => void;
  setExpandedKeys: (keys: Key[]) => void;
  getExpandedKeys: () => Key[];
  setSelectedKeys: (keys: Key[]) => void;
  getSelectedKeys: () => Key[];
  getCheckStrictly: () => boolean;
  setCheckedKeys: (keys: CheckKeys) => void;
  getCheckedKeys: () => CheckKeys;
  filterByLevel: (level: number) => void;
  insertNodeByKey: (opt: InsertNodeParams) => void;
  insertNodesByKey: (opt: InsertNodeParams) => void;
  deleteNodeByKey: (key: string) => void;
  updateNodeByKey: (
    key: string,
    node: Omit<TreeDataItem, 'key'>,
    list?: TreeDataItem[],
  ) => void;
  setSearchValue: (value: string) => void;
  getSearchValue: () => string;
  getSelectedNode: (
    key: Key,
    treeList?: TreeItem[],
    selectNode?: null | TreeItem,
  ) => null | TreeItem;
}

export interface HeaderEmits {
  (e: 'strictlyChange', f: boolean): void;
  (e: 'search', value: string): void;
}

export interface HeaderProps {
  // 标题提示语
  helpMessage?: string | string[];
  // 标题
  title?: string;
  // 是否显示工具栏
  toolbar?: boolean;
  // 显示搜索框
  search?: boolean;
  // 选择所有
  checkAll?: Fn;
  // 展开所有
  expandAll?: Fn;
  // 工具栏是否显示 层级关联按钮
  toolbarStrictly?: boolean;
  // 是否显示选择框
  checkable?: boolean;
  // 默认搜索的内容
  searchText?: string;
  // checkable 状态下节点选择完全受控（父子节点选中状态不再关联）
  checkStrictly?: boolean;
}
